package com.netcracker.util.service;

import com.netcracker.db.exception.DBException;
import com.netcracker.entity.User;
import com.netcracker.entity.record.UserRecord;
import com.netcracker.util.dao.DAOFacade;
import com.netcracker.util.hash.Hasher;
import com.netcracker.util.service.exception.DataTransmittingException;
import com.netcracker.util.service.exception.NullDataException;
import com.netcracker.util.service.exception.WrongUserException;
import java.security.NoSuchAlgorithmException;

public class UserService {
        
    private DAOFacade daoFacade;
    
    public UserService(DAOFacade daoFacade) {
        this.daoFacade = daoFacade;
    }
    
    public void setDAOFacade(DAOFacade daoFacade) {
        this.daoFacade = daoFacade;
    }

    public User authorize(String login, String password) throws DataTransmittingException, 
            NoSuchAlgorithmException, NullDataException {
        try {
            User user = daoFacade.getUserDAO().findByLogin(login);
            if (user == null) 
                throw new NullDataException("Authorization fault");
            if (checkPassword(user.getPasswordHash(), password)) 
                return makeNullableUser(user);          
            else
                throw new NullDataException("Authorization fault");
        } catch (DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }

    public User getUserInformation(int id) throws DataTransmittingException, NullDataException {
        User user = null;
        try {
            user = daoFacade.getUserDAO().find(id);
        } catch (DBException e) {
            throw new DataTransmittingException(e.getMessage(), e);
        }
        if (user == null)
        {
            throw new NullDataException("No one user was found");
        }
        return user;
    }
    
    public void changeUserInfo(UserRecord userRecord) throws WrongUserException, DataTransmittingException {
        try {
            User user = daoFacade.getUserDAO().findByLogin(userRecord.getLogin());
            if (user == null) throw new WrongUserException("Wrong user id!");           
            userRecord.setLogin(user.getLogin());
            userRecord.setPasswordHash(user.getPasswordHash());
            userRecord.setRegisterDate(user.getRegisterDate());
            userRecord.setRight(user.getRight());           
            checkData(userRecord);
            daoFacade.getUserDAO().edit(userRecord);
        } catch (DBException e) {
            throw new DataTransmittingException(e.getMessage(), e);
        }
    }
    
    public void changeUserPassword(String login, String newPassword, String oldPassword) 
            throws DataTransmittingException, NoSuchAlgorithmException, WrongUserException {
        if (login == null || newPassword == null || oldPassword == null) 
            throw new WrongUserException("The data must not be null!");
        try {
            User user = daoFacade.getUserDAO().findByLogin(login);
            if (user == null)
                throw new WrongUserException("Wrong user id!");
            if (checkPassword(user.getPasswordHash(), oldPassword))
                daoFacade.getUserDAO().changePassword(user.getId(), Hasher.hashString(newPassword));
            else
                throw new WrongUserException("Wrong old password!");
        } catch (DBException e) {
            throw new DataTransmittingException(e.getMessage(), e);
        }
    }

    public void registerUser(UserRecord userRecord) throws WrongUserException, DataTransmittingException, 
            NoSuchAlgorithmException {
        try {
            checkData(userRecord);
            User user = daoFacade.getUserDAO().findByLogin(userRecord.getLogin());
            if (user != null) throw new WrongUserException("User with this login already exists.");
            userRecord.setPasswordHash(Hasher.hashString(userRecord.getPasswordHash()));
            daoFacade.getUserDAO().create(userRecord);
        } catch (DBException e) {
            throw new DataTransmittingException(e.getMessage(), e);
        }
    }

    private void checkData(UserRecord userRecord) throws WrongUserException {
        if (userRecord.getFullName().equals("") || userRecord.getFullName() == null)
        {
            throw new WrongUserException("User name is wrong!");
        }
        if (userRecord.getDateOfBirth()==null)
        {
            throw new WrongUserException("The date must not be null!");
        }
        if (userRecord.getRight()==null)
        {
            throw new WrongUserException("The right must not be null!");
        }
        if (userRecord.getPasswordHash()==null || "".equals(userRecord.getPasswordHash()))
        {
            throw new WrongUserException("User password is wrong!");
        }
    }

    private User makeNullableUser(User user)
    {
        user.setCountry(null);
        user.setPasswordHash(null);
        user.setRegisterDate(null);
        user.setFullName(null);
        user.setDateOfBirth(null);
        return user;
    }

    private boolean checkPassword(String actual, String entered) throws NoSuchAlgorithmException {
        return Hasher.checkHashesEquals(actual, Hasher.hashString(entered));
    }
}
